home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Edition 10 / FreelogHS10.iso / Buzz / Buzz_Advanced_Pack.exe / {app} / Dev / Noise / Noise.cpp next >
C/C++ Source or Header  |  2001-08-27  |  7KB  |  399 lines

  1.  
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <assert.h>
  5. #include <math.h>
  6. #include <float.h>
  7. #include "../../MachineInterface.h"
  8. #include "../../dsplib/dsplib.h"
  9.  
  10. #pragma optimize ("a", on)
  11.  
  12. #define MAX_TRACKS                8
  13.  
  14. #define EGS_ATTACK                0
  15. #define EGS_SUSTAIN                1 
  16. #define EGS_RELEASE                2
  17. #define EGS_NONE                3
  18.  
  19. #define MIN_AMP                    (0.0001 * (32768.0 / 0x7fffffff))
  20.  
  21. double const oolog2 = 1.0 / log(2);
  22.  
  23. CMachineParameter const paraAttack = 
  24.     pt_word,                                        // type
  25.     "Attack",
  26.     "Attack time in ms",                            // description
  27.     1,                                                // MinValue    
  28.     0xffff,                                            // MaxValue
  29.     0,                                                // NoValue
  30.     MPF_STATE,                                        // Flags
  31.     16
  32. };
  33.  
  34. CMachineParameter const paraSustain = 
  35. {  
  36.     pt_word,                                        // type
  37.     "Sustain",
  38.     "Sustain time in ms",                            // description
  39.     1,                                                // MinValue    
  40.     0xffff,                                            // MaxValue
  41.     0,                                                // NoValue
  42.     MPF_STATE,                                        // Flags
  43.     16
  44. };
  45.  
  46. CMachineParameter const paraRelease = 
  47.     pt_word,                                        // type
  48.     "Release",
  49.     "Release time in ms",                            // description
  50.     1,                                                // MinValue    
  51.     0xffff,                                            // MaxValue
  52.     0,                                                // NoValue
  53.     MPF_STATE,                                        // Flags
  54.     512
  55. };
  56.  
  57. CMachineParameter const paraColor = 
  58.     pt_word,                                        // type
  59.     "Color",
  60.     "Noise color (0=black, 1000=white)",            // description
  61.     0,                                                // MinValue    
  62.     0x1000,                                            // MaxValue
  63.     0xffff,                                            // NoValue
  64.     MPF_STATE,                                        // Flags
  65.     0x1000
  66. };
  67.  
  68. CMachineParameter const paraVolume = 
  69.     pt_byte,                                        // type
  70.     "Volume",
  71.     "Volume [sustain level] (0=0%, 80=100%, FE=~200%)",    // description
  72.     0,                                                // MinValue    
  73.     0xfe,                                              // MaxValue
  74.     0xff,                                            // NoValue
  75.     MPF_STATE,                                        // Flags
  76.     0x80
  77. };
  78.  
  79. CMachineParameter const paraTrigger = 
  80.     pt_switch,                                        // type
  81.     "Trigger",
  82.     "Trigger (1=on, 0=off)",                        // description
  83.     -1,                                             // MinValue    
  84.     -1,                                                  // MaxValue
  85.     SWITCH_NO,                                        // NoValue
  86.     0,                                                // Flags
  87.     0
  88. };
  89.  
  90.  
  91. CMachineParameter const *pParameters[] = { 
  92.     // track
  93.     ¶Attack,
  94.     ¶Sustain,
  95.     ¶Release,
  96.     ¶Color,
  97.     ¶Volume,
  98.     ¶Trigger
  99. };
  100.  
  101. #pragma pack(1)
  102.  
  103. class tvals
  104. {
  105. public:
  106.     word attack;
  107.     word sustain;
  108.     word release;
  109.     word color;
  110.     byte volume;
  111.     byte trigger;
  112.  
  113. };
  114.  
  115. #pragma pack()
  116.  
  117. CMachineInfo const MacInfo = 
  118. {
  119.     MT_GENERATOR,                            // type
  120.     MI_VERSION,
  121.     0,                                        // flags
  122.     1,                                        // min tracks
  123.     MAX_TRACKS,                                // max tracks
  124.     0,                                        // numGlobalParameters
  125.     6,                                        // numTrackParameters
  126.     pParameters,
  127.     0, 
  128.     NULL,
  129. #ifdef _DEBUG
  130.     "Jeskola Noise Generator (Debug build)",            // name
  131. #else
  132.     "Jeskola Noise Generator",
  133. #endif
  134.     "Noise",                                // short name
  135.     "Oskari Tammelin",                         // author
  136.     NULL
  137. };
  138.  
  139. class mi;
  140.  
  141. class mi;
  142.  
  143. class CTrack
  144. {
  145. public:
  146.     void Tick(tvals const &tv);
  147.     void Stop();
  148.     void Reset();
  149.     void Generate(float *psamples, int numsamples);
  150.     void Noise(float *psamples, int numsamples);
  151.  
  152.     int MSToSamples(double const ms);
  153.  
  154. public:
  155.     double Amp;
  156.     double AmpStep;
  157.     double S1;
  158.     double S2;
  159.  
  160.     float Volume;
  161.     int Pos;
  162.     int Step;
  163.     int RandStat;
  164.     
  165.     int EGStage;
  166.     int EGCount;
  167.     int Attack;
  168.     int Sustain;
  169.     int Release;
  170.  
  171.     mi *pmi;
  172. };
  173.  
  174. class mi : public CMachineInterface
  175. {
  176. public:
  177.     mi();
  178.     virtual ~mi();
  179.  
  180.     virtual void Init(CMachineDataInput * const pi);
  181.     virtual void Tick();
  182.     virtual bool Work(float *psamples, int numsamples, int const mode);
  183.     virtual void SetNumTracks(int const n) { numTracks = n; }
  184.     virtual void Stop();
  185.  
  186. public:
  187.     int numTracks;
  188.     CTrack Tracks[MAX_TRACKS];
  189.  
  190.     tvals tval[MAX_TRACKS];
  191.  
  192. };
  193.  
  194. DLL_EXPORTS
  195.  
  196. mi::mi()
  197. {
  198.     GlobalVals = NULL;
  199.     TrackVals = tval;
  200.     AttrVals = NULL;
  201. }
  202.  
  203. mi::~mi()
  204. {
  205.  
  206. }
  207.  
  208. inline int CTrack::MSToSamples(double const ms)
  209. {
  210.     return (int)(pmi->pMasterInfo->SamplesPerSec * ms * (1.0 / 1000.0));
  211. }
  212.  
  213. inline double CalcStep(double from, double to, int time)
  214. {
  215.     assert(from > 0);
  216.     assert(to > 0);
  217.     assert(time > 0);
  218.     return pow(to / from, 1.0 / time);
  219. }
  220.  
  221. void CTrack::Reset()
  222. {
  223.     EGStage = EGS_NONE;
  224.  
  225.     Attack = MSToSamples(16);
  226.     Sustain = MSToSamples(16);
  227.     Release = MSToSamples(512);
  228.  
  229.     Pos = 0;
  230.     Step = 65536;
  231.     Volume = 1.0;
  232.     S1 = S2 = 0;
  233.     RandStat = 0x16BA2118;
  234. }
  235.  
  236. void mi::Init(CMachineDataInput * const pi)
  237. {
  238.     for (int c = 0; c < MAX_TRACKS; c++)
  239.     {
  240.         Tracks[c].pmi = this;
  241.         Tracks[c].Reset();
  242.     }
  243.  
  244. }
  245.  
  246. void CTrack::Tick(tvals const &tv)
  247. {
  248.     if (tv.attack != paraAttack.NoValue)
  249.         Attack = MSToSamples(tv.attack);
  250.  
  251.     if (tv.sustain != paraSustain.NoValue)
  252.         Sustain = MSToSamples(tv.sustain);
  253.  
  254.     if (tv.release != paraRelease.NoValue)
  255.         Release = MSToSamples(tv.release);
  256.  
  257.     if (tv.color != paraColor.NoValue)
  258.         Step = tv.color * 16;    // 0..4096 -> 0..65536
  259.     
  260.     if (tv.volume != paraVolume.NoValue)
  261.         Volume = (float)(tv.volume * (1.0 / 0x80));
  262.  
  263.     if (tv.trigger != SWITCH_NO)
  264.     {
  265.         if (Volume > 0)
  266.         {
  267.             EGStage = EGS_ATTACK;
  268.             EGCount = Attack;
  269.             Amp = MIN_AMP;
  270.             AmpStep = CalcStep(MIN_AMP, Volume * (32768.0 / 0x7fffffff), Attack);
  271.         }
  272.     }
  273. }
  274.  
  275. void CTrack::Noise(float *psamples, int numsamples)
  276. {
  277.     double amp = Amp;
  278.     double const ampstep = AmpStep;        
  279.     double s1 = S1;
  280.     double s2 = S2;
  281.     int const step = Step;
  282.     int stat = RandStat;
  283.     int pos = Pos;
  284.  
  285.     int c = numsamples;
  286.     do
  287.     {
  288.         *psamples++ = (float)(s1 + (s2 - s1) * (pos * 1.0 / 65536.0));
  289.         amp *= ampstep;
  290.  
  291.         pos += step;
  292.         if (pos & 65536)
  293.         {
  294.             s1 = s2;
  295.             stat = ((stat * 1103515245 + 12345) & 0x7fffffff) - 0x40000000;
  296.             s2 = stat * amp;
  297.  
  298.             pos -= 65536;
  299.         }
  300.  
  301.     } while(--c);
  302.  
  303.     Pos = pos;
  304.     S2 = s2;
  305.     S1 = s1;
  306.     RandStat = stat;
  307.     Amp = amp;
  308. }
  309.  
  310. void CTrack::Generate(float *psamples, int numsamples)
  311. {
  312.     do
  313.     {
  314.         int const c = __min(EGCount, numsamples);
  315.         assert(c > 0);
  316.  
  317.         if (EGStage != EGS_NONE)
  318.             Noise(psamples, c);
  319.         else
  320.             memset(psamples, 0, c * sizeof(float));
  321.         
  322.         numsamples -= c;
  323.         psamples += c;
  324.         EGCount -= c;
  325.  
  326.         if (!EGCount)
  327.         {
  328.             switch(++EGStage)
  329.             {
  330.             case EGS_SUSTAIN:
  331.                 EGCount = Sustain;
  332.                 AmpStep = 1.0;
  333.                 break;
  334.             case EGS_RELEASE:
  335.                 EGCount = Release;
  336.                 AmpStep = CalcStep(Amp, MIN_AMP, Release);
  337.                 break;
  338.             case EGS_NONE:
  339.                 EGCount = 0x7fffffff;
  340.                 break;
  341.             }
  342.         }
  343.  
  344.         
  345.  
  346.     } while(numsamples > 0);
  347. }
  348.  
  349. void mi::Tick()
  350. {
  351.     for (int c = 0; c < numTracks; c++)
  352.         Tracks[c].Tick(tval[c]);
  353.  
  354. }
  355.  
  356. bool mi::Work(float *psamples, int numsamples, int const)
  357. {
  358.     bool gotsomething = false;
  359.  
  360.     for (int c = 0; c < numTracks; c++)
  361.     {
  362.         if (Tracks[c].EGStage != EGS_NONE)
  363.         {
  364.             if (!gotsomething)
  365.             {
  366.                 Tracks[c].Generate(psamples, numsamples);
  367.                 gotsomething = true;
  368.             }
  369.             else
  370.             {
  371.                 float *paux = pCB->GetAuxBuffer();
  372.                 Tracks[c].Generate(paux, numsamples);
  373.  
  374.                 DSP_Add(psamples, paux, numsamples);
  375.  
  376.             }
  377.         }
  378.     }
  379.  
  380.     return gotsomething;
  381. }
  382.  
  383. void CTrack::Stop()
  384. {
  385.     EGStage = EGS_NONE;
  386. }
  387.  
  388. void mi::Stop()
  389. {
  390.     for (int c = 0; c < numTracks; c++)
  391.         Tracks[c].Stop();
  392. }
  393.  
  394.